<?php
/**
 * Read schema config file
 * @author Artur Kmera <artur.kmera@3code.pl>
 * @version 0.9
 * @package ORM
 * @subpackage Schema
 * @link http://arrowplatform.org/orm
 * @copyright 2011 Arrowplatform 
 * @license GNU LGPL
*/
class SchemaReader implements ISchemaReader{
	
	/**
	 * (non-PHPdoc)
	 * @see ISchemaReader::readSchemaFromFile()
	 */
	public function readSchemaFromFile($file){
		$tables = array();	
		//$tables =  $this->generateCache($file);
		//load XML file
		$xml = file_get_contents($file);
		//namespace must be deleted in order for this importer to work
		$xml = str_replace('xmlns="http://db.apache.org/ddlutils/schema/1.1"','',$xml);
		$sxml = simplexml_load_string($xml);
		
		$tablesSet = $sxml->xpath('/schema/table');

		$schema = new Schema();
		$schema->version = (string) $sxml["version"];
	    $schema->autoIncrementBuildVersion = "".$sxml["autoIncrementBuildVersion"]=="true"?true:false;
		
	    foreach( $tablesSet as $tableNode ){
	    	$table = $this->readTable($schema, $tableNode);
	    	$schema->addTable($table); 
	    }
	    
	    /**
	     * We need loaded whole schema to read f keys
	     */
		foreach( $tablesSet as $node ){
	    	$table = $schema->getTableByTable((string)$node['name']);
	    	foreach( $node->children() as $tag => $_node ){
		    	switch($tag){
		    		case 'field': break;
		    		case 'index': break;
		    		case 'foreign-key':
		    			$foreignKey = $this->readForeignKey($schema, $table, $_node);
		    			$table->addForeignKey($foreignKey);
		    		break; 		
		    		default:
		    			throw new SchemaException("Unknow schema element '$tag'");
		    	}
	    	}
	    }
	    

	    return $schema;
	}
	
	/**
	 * Reads table information and create Table object
	 * @param Schema
	 * @param XmlElement
	 * @return Table $node
	 */
	public function readTable( Schema $schema, $node ){
		$table = new Table();
	    $table->setClasspath((string) $node['classpath']);
	    $table->setBaseClasspath((string) $node['baseClasspath']);
	    $table->setTableName((String)$node['name']);
	    
	    
	    foreach( $node->children() as $tag => $node ){
	    	switch($tag){
	    		case 'field':
	    			$field = $this->readField($table, $node);
	    			$table->addField( $field );
	    		break;
	    		case 'index':
	    			$field = $this->readIndex($table, $node);
	    			$table->addIndex( $field );
	    		break;
	    		case 'foreign-key': break;
					//do nothing we read f keys later
	    		break; 		
	    		default:
	    			throw new SchemaException("Unknow schema element '$tag'");
	    	}
	    }
	    
		return $table;
	}
	
	/**
	 * Reads field information and create Field object
	 * @param Table
	 * @param XmlElement
	 * @return Field 
	 */
	public function readField( Table $table, $node ){
		$field = new Field();
		$field->setName( (String) $node["name"]);
		$field->setOldName( (String) $node["oldName"] );
		$field->setType( (String) $node["type"] );
		$field->setAutoincrement( ( isset( $node["autoIncrement"] ) && $node["autoIncrement"]."" == "true" )?true:false );
		$field->setPKey( ( isset( $node["primaryKey"] ) && $node["primaryKey"]."" == "true" )?true:false );
		$field->setSize( (int) $node["size"] );
		$field->setRequired( ( isset( $node["required"] ) && $node["required"]."" == "true" )?true:false );
		
		return $field;
		
	}
	
	/**
	 * Reads foreign key information and create ForeignKey object
	 * $param Schema
	 * @param Table
	 * @param XmlElement
	 * @return ForeignKey 
	 * @todo Implement
	 */
	public function readForeignKey(  Schema $schema, Table $table, $node ){
		$fKey = new ForeignKey();
		$fKey->foreignTable = $schema->getTableByTable((string) $node["foreignTable"]);
		$fKey->onUpdate = (string) $node["onUpdate"];
		$fKey->onDelete = (string) $node["onDelete"];
		
		$fKeyReferece = new ForeignKeyReference();
		$fKeyReferece->setLocalFieldName((string) $node->reference[0]["local"]);
		$fKeyReferece->setForeignFieldName((string) $node->reference[0]["foreign"]);
		$fKey->addReference($fKeyReferece);
		
		return $fKey;
	}
	
	/**
	 * Reads index information and create Index object
	 * @param Table
	 * @param XmlElement
	 * @return Index
	 * @todo Implement
	 */
	public function readIndex( Table $table, $node ){
		$index = new Index();
		$index->setName((string) $node->name );
		$index->setType( isset($node["type"])?(string)$node["type"]:'BTREE' );
		
		foreach( $node->children() as $tag => $_node ){
			if($tag == 'index-field'){
				$field =  $table->getFieldByName( (string) $_node["name"]);
				if($field == null)
					throw new SchemaException( "Field declared in index not finded in table (field: '{$_node["name"]}', table: '{$table->table}')" );
				else
					$index->addFieldName( $field->getName() ); 
			}
		}
		return $index;
	}
	
	
	
	
}
?>